package redis

import (
	"apiManageGo/src/core/common/config"
	"apiManageGo/src/core/common/logs"
	"bytes"
	"context"
	"github.com/redis/go-redis/v9"
	"go.uber.org/zap"
	"text/template"
	"time"
)

var client *redis.Client
var ctx context.Context

func init() {
	if config.GetConfig().Redis.Enabled {
		done := make(chan string)
		//异步拼接
		go func() {
			//拼接 addr
			addrTemplate := "{{.Addr}}:{{.Port}}"
			temp, err := template.New("addr").Parse(addrTemplate)
			if err != nil {
				panic(err)
			}

			templateData := map[string]string{
				"Addr": config.GetConfig().Redis.Addr,
				"Port": config.GetConfig().Redis.Port,
			}
			var addr bytes.Buffer
			err = temp.Execute(&addr, templateData)
			if err != nil {
				panic(err)
			}
			done <- addr.String()
		}()

		//等待拼接完成
		addrString := <-done

		client = redis.NewClient(&redis.Options{
			Addr:         addrString,                        // Redis地址
			Password:     config.GetConfig().Redis.Password, // Redis链接密码
			DB:           config.GetConfig().Redis.Db,       // Redis库，逻辑分区数，默认为0
			WriteTimeout: 600 * time.Millisecond,            // 写超时时间，这里是600毫秒
			ReadTimeout:  300 * time.Millisecond,            // 读超时时间，这里是300毫秒
			DialTimeout:  3 * time.Minute,                   // 连接超时时间
			PoolSize:     1000,                              // 连接池大小
			MinIdleConns: 3,                                 // 最小空闲连接数
		})

		ctx = context.Background()
		data := client.Ping(ctx)
		if data.Err() != nil {
			logs.Error("Redis连接失败：", zap.Error(data.Err()))
		} else {
			logs.Info("Redis连接成功")
		}
	}

}

// Hset 判断键是否存在
func Hset(key string, value ...interface{}) {
	client.HSet(ctx, key, value)
}

// Set 设置键值对
func Set(key string, value interface{}, expiration time.Duration) {
	err := client.Set(ctx, key, value, expiration).Err()
	if err != nil {
		logs.Error("设置Redis键值对失败：", zap.Error(err))
	}
}

// Get 获取键值对
func Get(key string) string {
	value, err := client.Get(ctx, key).Result()
	if err != nil {
		logs.Error("获取Redis键值对失败：", zap.Error(err))
		return ""
	}
	return value
}

// Del 删除键值对
func Del(key string) {
	err := client.Del(ctx, key).Err()
	if err != nil {
		logs.Error("删除Redis键值对失败：", zap.Error(err))
	}
}

// Eexpire 设置键值对过期时间
func Expire(key string, expiration time.Duration) {
	err := client.Expire(ctx, key, expiration).Err()
	if err != nil {
		logs.Error("设置Redis键值对过期时间失败：", zap.Error(err))
	}
}
